package org.shijiagen.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.shijiagen.clients.ProductClient;
import org.shijiagen.order.mapper.OrderMapper;
import org.shijiagen.order.service.OrderService;
import org.shijiagen.param.OrderParam;
import org.shijiagen.param.PageParam;
import org.shijiagen.param.ProductCollectParam;
import org.shijiagen.pojo.Order;
import org.shijiagen.pojo.Product;
import org.shijiagen.to.OrderToProduct;
import org.shijiagen.utils.R;
import org.shijiagen.vo.OrderVo;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    private final RabbitTemplate rabbitTemplate;

    private final ProductClient productClient;

    private final OrderMapper orderMapper;

    @Override
    public List<List<OrderVo>> list(Integer userId) {
        List<Order> orders = this.list(new QueryWrapper<Order>().eq("user_id", userId));
        Map<Long, List<Order>> groupOrder = orders.stream().collect(Collectors.groupingBy(Order::getOrderId));
        ProductCollectParam productCollectParam = new ProductCollectParam();
        productCollectParam.setProductIds(orders.stream().map(Order::getProductId).toList());
        Map<Integer, Product> productMap = productClient.cartProductByIds(productCollectParam).stream().collect(Collectors.toMap(Product::getProductId, product -> product));
        List<List<OrderVo>> result = new ArrayList<>();
        groupOrder.forEach((id,orderList)->{
            List<OrderVo> orderVos = new ArrayList<>();
            orderList.forEach(order -> {
                OrderVo orderVo = new OrderVo();
                BeanUtils.copyProperties(order,orderVo);
                orderVo.setProductName(productMap.get(order.getProductId()).getProductName());
                orderVo.setProductPicture(productMap.get(order.getProductId()).getProductPicture());
                orderVos.add(orderVo);
            });
            result.add(orderVos);
        });
        return result;
    }

    @Override
    public void save(OrderParam orderParam) {
        // 要在购物车删除的商品id集合
        List<Integer> cartIds = new ArrayList<>();
        // 需要删除的商品库存集合
        List<OrderToProduct> productBuy = new ArrayList<>();
        // 保存在数据库里的订单数据集合
        List<Order> orders = new ArrayList<>();
        // 统一批订单的唯一主键
        long orderId = System.currentTimeMillis();
        orderParam.getProducts().forEach(product->{
            // 拿到购物车的id放入集合
            cartIds.add(product.getId());
            // 拿到对应商品的购物车数量放到集合
            OrderToProduct orderToProduct = new OrderToProduct();
            orderToProduct.setNum(product.getNum());
            orderToProduct.setProductId(product.getProductID());
            productBuy.add(orderToProduct);
            // 生成订单数据并放入订单数据集合
            Order order = new Order();
            order.setOrderId(orderId);
            order.setOrderTime(orderId);
            order.setUserId(orderParam.getUserId());
            order.setProductId(product.getProductID());
            order.setProductNum(product.getNum());
            order.setProductPrice(product.getPrice());
            orders.add(order);
        });
        // 订单数据批量保存
        this.saveBatch(orders);
        // 发送购物车清空消息
        rabbitTemplate.convertAndSend("topic.ex","clear.cart",cartIds);
        // 发送商品库存减少消息
        rabbitTemplate.convertAndSend("topic.ex","sub.number",productBuy);
    }

    @Override
    public R check(Integer productId) {
        Long count = baseMapper.selectCount(new QueryWrapper<Order>().eq("product_id", productId));
        return count > 0 ? R.fail("购物车中有"+count+"项引用该商品，删除失败!"):R.ok("无订单引用，删除成功！");
    }

    @Override
    public R adminList(PageParam pageParam) {
        // 计算分页参数
        int offset = (pageParam.getCurrentPage()-1)*pageParam.getPageSize();
        int pageSize = pageParam.getPageSize();
        return R.ok("订单数据查询成功！", orderMapper.selectAdminOrder(offset,pageSize));
    }
}
